package pe.com.bbva.ge.negocio.impl;

import java.util.Properties;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pe.com.bbva.ge.domain.seguridad.Rol;
import pe.com.bbva.ge.domain.seguridad.Usuario;
import pe.com.bbva.ge.negocio.SeguridadNegocio;
import pe.com.bbva.ge.persistencia.orm.SeguridadORM;
import pe.com.bbva.ge.utileria.Constante;
import pe.com.bbva.ge.vista.vaadin.ui.utileria.exception.BBVAServiceExcepcion;
import pe.com.bbva.ge.vista.vaadin.ui.utileria.exception.ValidacionException;

import com.grupobbva.bc.per.tele.ldap.comunes.IILDPeExcepcion;
import com.grupobbva.bc.per.tele.ldap.directorio.IILDPeUsuario;
//import pe.com.bbva.ge.persistencia.orm.hibernate.BaseORMHibernate;

@Service
public class SeguridadNegocioImpl extends CrudNegocioImpl implements SeguridadNegocio{

	Logger logger = LogManager.getLogger(SeguridadNegocioImpl.class.getName());
	private static final long serialVersionUID = 1069924240377681947L;
	
	private static final String KEY_VALIDATOR = "ldap.validator";
	private static final String KEY_URL = "ldap.url";
	private static final String KEY_EMPLEADOS = "ldap.empleados";
	
	@Value("${"+KEY_VALIDATOR+"}")
	private String validator;

	@Value("${"+KEY_URL+"}")
	private String url;
	
	@Value("${"+KEY_EMPLEADOS+"}")
	private String empleados;
	
	@Autowired
	private SeguridadORM seguridadORM;
	
	@Override
	@Transactional
	public Usuario login(String loginUsuario, String password) {
		autenticacionLDAP(loginUsuario, password);
		IILDPeUsuario usuarioLDAP = obtenerUsuarioLDAP(loginUsuario);
		String cargo;
		
		Rol rol = seguridadORM.verificarMembresia(
				loginUsuario, 
				cargo = usuarioLDAP.getCargo() != null ? usuarioLDAP.getCargo().getCodigo() : StringUtils.EMPTY);
		
		if(rol == null)
		{
			return null;//FIXME botar EXCEPCION DE seguridad
		}
		
		Usuario usuario = seguridadORM.obtenerUsuario(loginUsuario);
		
		boolean esNuevo = false;
		
		if(esNuevo = usuario==null)
		{
			usuario = new Usuario();
		}
		
		usuario.setNombres(usuarioLDAP.getNombre());
		usuario.setPaterno(usuarioLDAP.getApellido1());
		usuario.setMaterno(usuarioLDAP.getApellido2());
		usuario.setRegistro(loginUsuario);
		usuario.setCargo(cargo);
		usuario.setRol(rol);
		
		if(esNuevo)
		{
			crear(usuario);
		}else
		{
			modificar(usuario);
		}
		
		return usuario;
	}
	
	private void autenticacionLDAP(String loginUsuario, String password) {
		StringBuilder mensaje = new StringBuilder();		
		mensaje.append("Parametros de Conexión LDAP: \n");
		mensaje.append(KEY_VALIDATOR).append("=").append(validator).append("\n");
		mensaje.append(KEY_URL).append("=").append(url).append("\n");
		mensaje.append(KEY_EMPLEADOS).append("=").append(empleados).append("\n");
		
		if (Constante.DESARROLLO.MODO.equalsIgnoreCase(validator))
		{
			mensaje.append("Ambiente de Desarrollo\n");
			logger.debug(mensaje.toString());
			return;
		}
		
		InitialDirContext ctx = null;
		Properties env = System.getProperties();
		Properties envLDAP = (Properties) env.clone();
		envLDAP.put(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.ldap.LdapCtxFactory");
		envLDAP.put(Context.PROVIDER_URL, url);
		envLDAP.put(Context.SECURITY_PRINCIPAL, "cn=" + loginUsuario + ","
				+ empleados);
		envLDAP.put(Context.SECURITY_CREDENTIALS, password);
		try {
			ctx = new InitialDirContext(envLDAP);			
		} catch (AuthenticationException e) {
			//mensaje.append("Error de autenticación: \n");
			logger.error(mensaje.toString(), e);
			throw new ValidacionException("login.ldap.validacion", null);
		} catch (NamingException e) {
			//mensaje.append("Error de conexión LDAP: \n");
			logger.error(mensaje.toString(), e);
			throw new BBVAServiceExcepcion("login.ldap.error", null, e);
		}
		finally
		{
			try {
				if(ctx!=null)
				{
					ctx.close();
				}
			} catch (NamingException e) {
				//mensaje.append("Error al cerrar la conexión LDAP: \n");
				logger.error("Problemas al Cerrar InitialDirContext " + ctx, e);
				throw new BBVAServiceExcepcion("login.ldap.error", null, e);
			}
		}
	}
	
	private IILDPeUsuario obtenerUsuarioLDAP(String loginUsuario) {
		IILDPeUsuario usuarioLDAP = null;
		
		try {
			usuarioLDAP = IILDPeUsuario.recuperarUsuario(loginUsuario);
		} catch (IILDPeExcepcion e) {
			throw new BBVAServiceExcepcion("login.ldap.obtener.usuario", new Object[]{loginUsuario}, e);
		}
		
		if(usuarioLDAP == null)
		{
			throw new BBVAServiceExcepcion("login.ldap.obtener.usuario", new Object[]{loginUsuario});
		}
		
		return usuarioLDAP;
	}
}
